package cn.fufeii.generator.util;

import cn.fufeii.generator.config.ConfigHolder;
import cn.fufeii.generator.config.GeneratorConfig;
import cn.fufeii.generator.config.GeneratorConfig.DataSource;
import cn.fufeii.generator.domain.ColumnDO;
import cn.fufeii.generator.domain.TableDO;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

/**
 * 数据库工具类
 *
 * @author FuFei
 */
public final class DatabaseUtil {

    private static final String SELECT_COLUMN = "SELECT COLUMN_NAME, COLUMN_COMMENT, COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = ? AND TABLE_SCHEMA = ? ORDER BY ORDINAL_POSITION";

    private static final String SELECT_TABLE = "SELECT TABLE_NAME, TABLE_COMMENT FROM INFORMATION_SCHEMA.`TABLES` WHERE TABLE_SCHEMA = ?";

    private static DataSource DATASOURCE;


    private static DataSource getDataSource() {
        if (DATASOURCE != null) {
            return DATASOURCE;
        }
        synchronized (DatabaseUtil.class) {
            if (DATASOURCE != null) {
                return DATASOURCE;
            }
            DATASOURCE = ConfigHolder.getDataSource();
            return DATASOURCE;
        }
    }


    /**
     * 查询某个数据库连接的所有表
     */
    public static List<TableDO> selectTables() {
        DataSource dataSource = getDataSource();
        List<TableDO> tables = new ArrayList<>();
        try (
                Connection conn = DriverManager.getConnection(dataSource.getUrl(), dataSource.getUsername(), dataSource.getPassword());
                PreparedStatement preparedStatement = conn.prepareStatement(SELECT_TABLE);
        ) {
            //获取数据库名称
            String dbName = getDbName(dataSource);
            //构造查询语句
            preparedStatement.setString(1, dbName);
            ResultSet resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                TableDO tableDO = new TableDO(resultSet.getString("TABLE_NAME"), resultSet.getString("TABLE_COMMENT"));
                tableDO.setColumnDOList(selectColumn(tableDO.getName()));
                tables.add(tableDO);
            }
            return tables;
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * 查询某个表的所有字段
     */
    public static List<ColumnDO> selectColumn(String tableName) {
        GeneratorConfig.DataSource dataSource = getDataSource();
        ArrayList<ColumnDO> columnInfoList = new ArrayList<>();
        try (
                Connection conn = DriverManager.getConnection(dataSource.getUrl(), dataSource.getUsername(), dataSource.getPassword());
                PreparedStatement preparedStatement = conn.prepareStatement(SELECT_COLUMN);
        ) {
            String dbName = getDbName(dataSource);
            preparedStatement.setString(1, tableName);
            preparedStatement.setString(2, dbName);
            //执行查询
            ResultSet resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                columnInfoList.add(new ColumnDO(resultSet.getString("COLUMN_NAME"), resultSet.getString("COLUMN_TYPE"), resultSet.getString("COLUMN_COMMENT")));
            }
            return columnInfoList;
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    /**
     * 获取数据库名称
     */
    private static String getDbName(GeneratorConfig.DataSource dataSource) {
        //mysql，返回/和?之间的字符
        String jdbcUrl = dataSource.getUrl();
        return jdbcUrl.substring(jdbcUrl.lastIndexOf("/") + 1, jdbcUrl.indexOf("?"));
    }

}
